/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package co.com.claro.administracionSolicitudes.ejb;

import co.com.claro.administracionSolicitudes.dao.exceptions.ClaroException;
import co.com.claro.administracionSolicitudes.db.EJBDatabaseSolicitudesLocal;
import co.com.claro.administracionSolicitudes.entity.Aplicacion;
import co.com.claro.administracionSolicitudes.entity.CertificacionUsuario;
import co.com.claro.administracionSolicitudes.entity.EstadosSolicitud;
import co.com.claro.administracionSolicitudes.entity.ParametrosPassword;
import co.com.claro.administracionSolicitudes.entity.PrivilegioSolicitud;
import co.com.claro.administracionSolicitudes.entity.Solicitud;
import co.com.claro.administracionSolicitudes.entity.Usuario;
import co.com.claro.administracionSolicitudes.entity.UsuarioTemporal;
import co.com.claro.administracionSolicitudes.entity.UsuariosPorAplicaciones;
import co.com.claro.administracionSolicitudes.entity.enums.AccionesEnum;
import co.com.claro.administracionSolicitudes.entity.enums.EstadoActividadEnum;
import co.com.claro.administracionSolicitudes.entity.enums.EstadoCertificacionEnum;
import co.com.claro.administracionSolicitudes.entity.enums.EstadosSolicitudEnum;
import co.com.claro.administracionSolicitudes.entity.enums.TipoSolicitudEnum;
import co.com.claro.administracionSolicitudes.seguridad.EJBSeguridadLocal;
import com.gammapeit.jms.ejb.MailMessageEJBLocal;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Stateless;

/**
 *
 * @author Mike
 */
@Stateless
public class EJBAdminSolicitudes implements EJBAdminSolicitudesLocal {

    @EJB
    private MailMessageEJBLocal localQueue;
    @EJB
    private EJBDatabaseSolicitudesLocal localBaseDatos;
    @EJB
    private EJBSeguridadLocal localSeguridad;

    private final static int ID_ADMIN_SOLICITUDES = 1;

    @Override
    public void saludar() {
        System.out.println("Hola el programa con EJB sirve para algo.");
    }

    @Override
    public void crearUsuario(Usuario usuario, boolean tieneUsuarioRed, int idAplicacion) throws ClaroException {
        Solicitud solicitud = new Solicitud();
        Calendar calendario = Calendar.getInstance();
        StringBuilder nombreUsuario = new StringBuilder(usuario.getNombres());
        Aplicacion aplicacion = new Aplicacion(idAplicacion);
        try {
            if (localBaseDatos.findUsuarioByNumeroDocumento(usuario.getNumeroDocumento()) == null) {
                if (!tieneUsuarioRed) {
                    localSeguridad.generarUsername(usuario);
                    ParametrosPassword parametros = localBaseDatos.findParametrosPassword((short) 1);

                    usuario.setPassword(localSeguridad.encriptarPassword(parametros.getDefaultPassword()));
                }

                localBaseDatos.crearUsuario(usuario);

                String descripcion = ResourceBundle.getBundle("mensajesEJB").getString("solicitudUsuario");
                nombreUsuario.append(" ");
                nombreUsuario.append(usuario.getApellidos());

                //se crea la descripción de la solicitud
                descripcion = MessageFormat.format(descripcion, nombreUsuario.toString());

                solicitud.setEstado(new EstadosSolicitud(EstadosSolicitudEnum.POR_APROBAR.getId()));
                solicitud.setDescripcion(descripcion);
                solicitud.setFechaSolicitud(new Date(calendario.getTimeInMillis()));
                solicitud.setIdSolicitante(usuario);
                solicitud.setGerenciaAprobadora(usuario.getGerencia());
                solicitud.setGerenciaAsignadora(localBaseDatos.findAplicacion(idAplicacion).getGerenciaAsignadora());
                solicitud.setUsuario(usuario.getUsuario());
                solicitud.setAplicacion(aplicacion);
                solicitud.setAccion(AccionesEnum.CREACION.getId());
                solicitud.setActivo(EstadoActividadEnum.ACTIVO.getId());

                localBaseDatos.crearSolicitud(solicitud);

                //Se envía correo al usuario solicitante
                notificarUsuario(obtenerMensajeCorreo(solicitud, true), solicitud.getIdSolicitante().getCorreo(), obtenerAsuntoSolicitud(solicitud.getIdSolicitud()));

                //Se envía correo al usuario responsable de la solicitud
                notificarUsuario(obtenerMensajeCorreo(solicitud, false),
                        obtenerCorreoUsuarioByUsername(
                                localBaseDatos.findGerenciaById(solicitud.getGerenciaAprobadora().getIdGerencia()).getUsernameAprobador()),
                        obtenerAsuntoSolicitud(solicitud.getIdSolicitud()));
            } else {
                throw new ClaroException("Ya existe un usuario con número de documento " + usuario.getNumeroDocumento() + " en el sistema", null);
            }
        } catch (ClaroException ex) {
            throw new ClaroException("Error insertando el usuario. | EJBAdminSolicitudes | crearUsuario -> " + ex.getMessage(), ex);
        }
    }

    @Override
    public void modificarPerfilUsuario(Usuario usuarioNuevo, Usuario usuarioActual) throws ClaroException {
        try {
            UsuarioTemporal temporal = new UsuarioTemporal(usuarioNuevo);
            temporal.setActivo(EstadoActividadEnum.ACTIVO.getId());

            String descripcion = ResourceBundle.getBundle("mensajesEJB").getString("solicitudPerfilUsuario");
            descripcion = MessageFormat.format(descripcion, usuarioNuevo.getNombres() + " " + usuarioNuevo.getApellidos());

            Solicitud solicitud = new Solicitud();
            solicitud.setActivo(EstadoActividadEnum.ACTIVO.getId());
            solicitud.setDescripcion(descripcion);
            solicitud.setEstado(new EstadosSolicitud(EstadosSolicitudEnum.POR_APROBAR.getId()));
            solicitud.setFechaSolicitud(new Date(Calendar.getInstance().getTimeInMillis()));
            solicitud.setIdSolicitante(usuarioNuevo);
            solicitud.setGerenciaAprobadora(usuarioActual.getGerencia());
            solicitud.setGerenciaAsignadora(localBaseDatos.findAplicacion(ID_ADMIN_SOLICITUDES).getGerenciaAsignadora());
            solicitud.setAplicacion(new Aplicacion(ID_ADMIN_SOLICITUDES));
            solicitud.setUsuario(usuarioNuevo.getUsername());
            solicitud.setAccion(AccionesEnum.CAMBIO_PERFIL.getId());

            localBaseDatos.crearSolicitud(solicitud);
            localBaseDatos.modificarUsuarioTemporal(temporal);

            //Se envía correo al usuario solicitante
            notificarUsuario(obtenerMensajeCorreo(solicitud, true),
                    solicitud.getIdSolicitante().getCorreo(),
                    obtenerAsuntoSolicitud(solicitud.getIdSolicitud()));

            //Se envía correo al usuario responsable de la solicitud (Aprobador)
            notificarUsuario(obtenerMensajeCorreo(solicitud, false),
                    obtenerCorreoUsuarioByUsername(solicitud.getGerenciaAprobadora().getUsernameAprobador()),
                    obtenerAsuntoSolicitud(solicitud.getIdSolicitud()));
        } catch (ClaroException ce) {
            throw new ClaroException("Error enviando la solicitud. | EJBAdminSolicitudes | enviarSolicitud -> " + ce.getMessage(), ce);
        }
    }

    @Override
    public void enviarSolicitudAplicacion(Solicitud solicitud, UsuariosPorAplicaciones usrxapps, AccionesEnum accion, short tipoAplicacion) throws ClaroException {
        try {

            if (tipoAplicacion == TipoSolicitudEnum.APLICACION.getId()) {
                validarSolicitudAplicacion(solicitud, accion);
            } else if (tipoAplicacion == TipoSolicitudEnum.ELEMENTOS.getId()) {

            } else if (tipoAplicacion == TipoSolicitudEnum.FIREWALL.getId()) {

            } else if (tipoAplicacion == TipoSolicitudEnum.REQUERIMIENTOS.getId()) {

            }

            localBaseDatos.crearSolicitud(solicitud);

            switch (accion) {
                case CREACION:
                    localBaseDatos.crearUsuarioPorAplicaciones(usrxapps);
                    break;
                default:
                    break;
            }

            //Se envía correo al usuario solicitante
            notificarUsuario(obtenerMensajeCorreo(solicitud, true),
                    solicitud.getIdSolicitante().getCorreo(),
                    obtenerAsuntoSolicitud(solicitud.getIdSolicitud()));

            //Se envía correo al usuario responsable de la solicitud (Aprobador)
            notificarUsuario(obtenerMensajeCorreo(solicitud, false),
                    obtenerCorreoUsuarioByUsername(solicitud.getGerenciaAprobadora().getUsernameAprobador()),
                    obtenerAsuntoSolicitud(solicitud.getIdSolicitud()));

        } catch (ClaroException ce) {
            throw new ClaroException("Error enviando la solicitud. | EJBAdminSolicitudes | enviarSolicitud -> " + ce.getMessage(), ce);
        }
    }

    @Override
    public void aprobarSolicitud(Solicitud solicitud) throws ClaroException {
        try {
            Calendar calendar = Calendar.getInstance();

            // si la aplicacion es Administración Solicitudes (IMPORTANTE, TIENE QUE SER EL ID 1 EN LA TABLA DE APLICACOINES) 
            // si es una solicitud de creacion que se haga todo el proceso automaticamente cuando se aprueba la solicitud
            // activando el usuario para esta aplicacion.
            // si es una solicitud de cambio de perfil de usuario que se haga todo el proceso automaticamente cuando 
            // se aprueba la solicitud, modificando el usuario con los cambios pedidos
            if (solicitud.getAplicacion().getIdAplicacion() == ID_ADMIN_SOLICITUDES) {

                List<Solicitud> solicitudes = generarSolicitudesAdminSolicitudes(solicitud);
                localBaseDatos.insertarSolicitudesMasivas(solicitudes);

                Usuario solicitante = solicitud.getIdSolicitante();

                if (solicitud.getAccion() == AccionesEnum.CREACION.getId()) {
                    solicitante.setUsuario("AdminSolicitudes");
                    solicitante.setEstado(EstadoActividadEnum.ACTIVO.getId());
                    localBaseDatos.modificarUsuario(solicitante);

                } else if (solicitud.getAccion() == AccionesEnum.CAMBIO_PERFIL.getId()) {
                    UsuarioTemporal temp = localBaseDatos.findUsuarioTemporalByIdUsuarioSolicitante(solicitante.getIdUsuario());

                    Usuario nuevo = temp.getUsuarioNuevo();
                    nuevo.setUsuario(solicitud.getUsuario());

                    localBaseDatos.modificarUsuario(nuevo);
                    localBaseDatos.borradoLogicoUsuarioTemporal(temp);

                } else if (solicitud.getAccion() == AccionesEnum.ELIMINACION.getId()) {
                    solicitante.setUsuario("AdminSolicitudes");
                    solicitante.setEstado(EstadoActividadEnum.INACTIVO.getId());
                    localBaseDatos.modificarUsuario(solicitante);
                }

                // Se envía correo al usuario solicitante
                notificarUsuario(obtenerMensajeCorreo(solicitud, true), solicitud.getIdSolicitante().getCorreo(),
                        obtenerAsuntoSolicitud(solicitud.getIdSolicitud()));

            } else {
                solicitud.setEstado(new EstadosSolicitud(EstadosSolicitudEnum.POR_ASIGNAR.getId()));
                solicitud.setFechaAprobacion(new Date(calendar.getTimeInMillis()));

                solicitud = localBaseDatos.modificarSolicitud(solicitud);

                // Se envía correo al usuario solicitante
                notificarUsuario(obtenerMensajeCorreo(solicitud, true), solicitud.getIdSolicitante().getCorreo(),
                        obtenerAsuntoSolicitud(solicitud.getIdSolicitud()));

                // Se envía correo al usuario responsable de la solicitud (Asignador)
                notificarUsuario(obtenerMensajeCorreo(solicitud, false),
                        obtenerCorreoUsuarioByUsername(solicitud.getGerenciaAsignadora().getUsernameAprobador()),
                        obtenerAsuntoSolicitud(solicitud.getIdSolicitud()));
            }

        } catch (ClaroException ce) {
            throw ce;
        } catch (Exception ex) {
            throw new ClaroException("Error aprobando la solicitud. | EJBAdminSolicitudes | aprobarSolicitud -> " + ex.getMessage(), ex);
        }

    }

    @Override
    public void asignarSolicitud(Solicitud solicitud) throws ClaroException {
        try {
            Calendar calendar = Calendar.getInstance();

            solicitud.setFechaAsignacion(new Date(calendar.getTimeInMillis()));
            solicitud.setEstado(new EstadosSolicitud(EstadosSolicitudEnum.POR_EJECUTAR.getId()));

            solicitud = localBaseDatos.modificarSolicitud(solicitud);

            //Se envía correo al usuario solicitante
            notificarUsuario(obtenerMensajeCorreo(solicitud, true),
                    solicitud.getIdSolicitante().getCorreo(),
                    obtenerAsuntoSolicitud(solicitud.getIdSolicitud()));

            //Se envía correo al usuario responsable de la solicitud (Ejecutor)
            notificarUsuario(obtenerMensajeCorreo(solicitud, false),
                    solicitud.getIdEjecutor().getCorreo(),
                    obtenerAsuntoSolicitud(solicitud.getIdSolicitud()));
        } catch (ClaroException ce) {
            throw ce;
        } catch (Exception ex) {
            throw new ClaroException("Error asignando la solicitud. | EJBAdminSolicitudes | asignarSolicitud -> " + ex.getMessage(), ex);
        }
    }

    @Override
    public void ejecutarSolicitud(Solicitud solicitud) throws ClaroException {
        try {
            Calendar calendar = Calendar.getInstance();

            solicitud.setFechaEjecucion(new Date(calendar.getTimeInMillis()));
            solicitud.setEstado(new EstadosSolicitud(EstadosSolicitudEnum.CERRADO.getId()));

            solicitud = localBaseDatos.modificarSolicitud(solicitud);

            //Se envía correo al usuario solicitante
            notificarUsuario(obtenerMensajeCorreo(solicitud, true),
                    solicitud.getIdSolicitante().getCorreo(),
                    obtenerAsuntoSolicitud(solicitud.getIdSolicitud()));
        } catch (ClaroException ce) {
            throw ce;
        } catch (Exception ex) {
            throw new ClaroException("Error ejecutando la solicitud. | EJBAdminSolicitudes | ejecutarSolicitud -> " + ex.getMessage(), ex);
        }
    }

    @Override
    public void cancelarSolicitud(Solicitud solicitud) throws ClaroException {

        //Si la solicitud es de creacion de usuario para el sistema de administracion de solicitudes (ID = 1 en tabla APLICACION)
        //Borrar al usuario del sistema (borrado logico -> activo = 1; estado = 1)
        if (solicitud.getAplicacion().getIdAplicacion() == ID_ADMIN_SOLICITUDES) {

            Usuario solicitante = solicitud.getIdSolicitante();

            if (solicitud.getAccion().equals(AccionesEnum.CREACION.getId())) {
                solicitante.setUsuario(solicitud.getUsuario());
                localBaseDatos.borradoLogicoUsuario(solicitante);
            } else if (solicitud.getAccion().equals(AccionesEnum.CAMBIO_PERFIL.getId())) {
                UsuarioTemporal u = localBaseDatos.findUsuarioTemporalByIdUsuarioSolicitante(solicitante.getIdUsuario());
                localBaseDatos.borradoLogicoUsuarioTemporal(u);
            }
        }

        localBaseDatos.modificarSolicitud(solicitud);
    }

    @Override
    public void certificarUsuario(List<UsuariosPorAplicaciones> aplicacionesEliminadas, List<UsuariosPorAplicaciones> aplicacionesCertificadas, Usuario usuarioCertificador) throws ClaroException {
        try {
            Date fecha = new Date();
            if (!aplicacionesEliminadas.isEmpty()) {
                List<Solicitud> solicitudes = generarListaSolicitudes(aplicacionesEliminadas, AccionesEnum.ELIMINACION);
                localBaseDatos.insertarSolicitudesMasivas(solicitudes);

                for (UsuariosPorAplicaciones uxa : aplicacionesEliminadas) {
                    CertificacionUsuario certificacion = new CertificacionUsuario();

                    certificacion.setEstadoCertificacion(EstadoCertificacionEnum.NO_CERTIFICADO.getId());
                    certificacion.setFechaCertificacion(fecha);
                    certificacion.setIdUsuarioAplicacion(uxa);
                    certificacion.setIdUsuarioCertificador(usuarioCertificador);

                    localBaseDatos.crearCertificacionUsuario(certificacion);
                }
            }
            if (!aplicacionesCertificadas.isEmpty()) {
                for (UsuariosPorAplicaciones uxa : aplicacionesCertificadas) {
                    CertificacionUsuario certificacion = new CertificacionUsuario();

                    certificacion.setEstadoCertificacion(EstadoCertificacionEnum.CERTIFICADO.getId());
                    certificacion.setFechaCertificacion(fecha);
                    certificacion.setIdUsuarioAplicacion(uxa);
                    certificacion.setIdUsuarioCertificador(usuarioCertificador);

                    localBaseDatos.crearCertificacionUsuario(certificacion);
                }

            }
        } catch (ClaroException ex) {
            throw new ClaroException("Error certificando al usuario. | EJBAdminSolicitudes | certificarUsuario -> " + ex.getMessage(), ex);
        }
    }

    @Override
    public void generarSolicitudMasivaBorradoUsuario(Usuario usuario) throws ClaroException {
        try {
            List<UsuariosPorAplicaciones> usuariosxApps = localBaseDatos.findAplicacionesByUsuario(usuario.getIdUsuario());
            List<Solicitud> solicitudes = generarListaSolicitudes(usuariosxApps, AccionesEnum.ELIMINACION);
            localBaseDatos.insertarSolicitudesMasivas(solicitudes);
        } catch (ClaroException ex) {
            throw new ClaroException("Error generando las solicitudes masivas. | EJBAdminSolicitudes | generarSolicitudMasivaBorrado -> " + ex.getMessage(), ex);
        }
    }

    @Override
    public void cambiarPassword(Usuario usuario) throws ClaroException {
        String password = usuario.getPassword();
        String passwordEncriptado;

        if (!isPasswordValido(password)) {
            throw new ClaroException("El password introducido no cumple con las reglas minimas de seguridad.");
        }

        passwordEncriptado = localSeguridad.encriptarPassword(usuario.getPassword());

        usuario.setPassword(passwordEncriptado);

        localBaseDatos.modificarUsuario(usuario);
    }

    @Override
    /**
     * Método encargado de enviar las notificaciones a los diferentes usuarios
     * del sistema
     */
    public void notificarUsuario(String mensaje, String receptores, String asunto) {
//        List<String> receptores = new ArrayList<String>();

//        receptores.add(destinatario);
        try {
            localQueue.enviarMail(receptores, mensaje, asunto);
        } catch (Exception ex) {
            Logger.getLogger(EJBAdminSolicitudes.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public String restablecerContrasena(String nombreUsuario) throws ClaroException {

        Usuario usuario = localSeguridad.findUsuarioActivoPorUsernameExacto(nombreUsuario);

        if (usuario != null) {
            if (usuario.getUsuarioRed() == 1) {
                return ResourceBundle.getBundle("mensajesEJB").getString("usuarioLdap");
            } else {
                ParametrosPassword parametros = localBaseDatos.findParametrosPassword((short) 1);

                usuario.setUsuario(usuario.getNombres() + usuario.getApellidos());
                usuario.setPassword(parametros.getDefaultPassword());

                cambiarPassword(usuario);

                String mensaje = ResourceBundle.getBundle("mensajesEJB").getString("mensajeRestablecerContrasena");

                MessageFormat.format(mensaje, usuario.getPassword());

                notificarUsuario(mensaje, usuario.getCorreo(), "Contraseña Reestablecida");
                return ResourceBundle.getBundle("mensajesEJB").getString("usuarioBD");
            }
        } else {
            return "El usuario " + nombreUsuario + " no existe";
        }
    }

    @Override
    public void aprobarSolicitudesMasivas(List<Solicitud> solicitudes) throws ClaroException {
        int i = 0;

        for (Solicitud solicitud : solicitudes) {
            aprobarSolicitud(solicitud);

            if (i++ % 20 == 0) {
                localBaseDatos.clearAndFlushSolicitudes();
            }
        }
    }

    @Override
    public void cancelarSolicitudesMasivas(List<Solicitud> solicitudes) throws ClaroException {
        int i = 0;

        for (Solicitud solicitud : solicitudes) {
            cancelarSolicitud(solicitud);

            if (i++ % 20 == 0) {
                localBaseDatos.clearAndFlushSolicitudes();
            }
        }
    }

    //++++++++++++++++++++++++++++++ MÉTODOS PRIVADOS DEL EJB +++++++++++++++++++++++++++++++
    /**
     * Método que valida que el password cumpla con los requisitos dentro de la
     * base de datos
     *
     * @param password, cadena de caracteres a validar
     * @return true, si cumple los requisitos de la base de datos false, si
     * alguno de los requisitos no se cumple
     */
    private boolean isPasswordValido(String password) {
        //Se deja así porque se definió que se va a dejar solo esa regla en la BD, 
        //por lo tanto siempre va a existir un único registro
        ParametrosPassword pp = localBaseDatos.findAllParametrosPasswordEntities().get(0);

        if (password.length() < pp.getMinCaracteres()) {
            return false;
        }

        StringBuilder regex = new StringBuilder("[A-Z]");
        int cantidadNumeros = 0;

        if (password.split(regex.toString()).length < pp.getMinMayusculas()) {
            return false;
        }

        regex.delete(0, regex.length());
        regex.append("[a-z]");

        if (password.split(regex.toString()).length < pp.getMinMinusculas()) {
            return false;
        }

        regex.delete(0, regex.length());
        regex.append("\\d+");

        String tempPass = password;

        for (int i = 0; i < pp.getMinNumeros(); i++) {
            if (tempPass.contains("0")) {
                tempPass = tempPass.replace("0", "");
                cantidadNumeros++;
                continue;
            }
            if (tempPass.contains("1")) {
                tempPass = tempPass.replace("1", "");
                cantidadNumeros++;
                continue;
            }
            if (tempPass.contains("2")) {
                tempPass = tempPass.replace("2", "");
                cantidadNumeros++;
                continue;
            }
            if (tempPass.contains("3")) {
                tempPass = tempPass.replace("3", "");
                cantidadNumeros++;
                continue;
            }
            if (tempPass.contains("4")) {
                tempPass = tempPass.replace("4", "");
                cantidadNumeros++;
                continue;
            }
            if (tempPass.contains("5")) {
                tempPass = tempPass.replace("5", "");
                cantidadNumeros++;
                continue;
            }
            if (tempPass.contains("6")) {
                tempPass = tempPass.replace("6", "");
                cantidadNumeros++;
                continue;
            }
            if (tempPass.contains("7")) {
                tempPass = tempPass.replace("7", "");
                cantidadNumeros++;
                continue;
            }
            if (tempPass.contains("8")) {
                tempPass = tempPass.replace("8", "");
                cantidadNumeros++;
                continue;
            }
            if (tempPass.contains("9")) {
                tempPass = tempPass.replace("9", "");
                cantidadNumeros++;
            }

        }
        return cantidadNumeros >= pp.getMinNumeros();
    }

    /**
     * Método encargado de generar la lista de solicitudes a partir de las
     * aplicaciones que tiene asociadas un usuario y una acción
     *
     * @param usuariosxApps, lista con las aplicaciones que tiene asociadas un
     * usuario
     * @param accion, la acción que se requiere para la solicitud: Crear,
     * Eliminar, Cambio Perfil, Cambio Password
     * @return List<Solicitud>, listado las solicitudes listas para enviar
     */
    private List<Solicitud> generarListaSolicitudes(List<UsuariosPorAplicaciones> usuariosxApps, AccionesEnum accion) {
        Calendar calendario = Calendar.getInstance();
        List<Solicitud> solicitudes = new ArrayList<>();

        for (UsuariosPorAplicaciones usuariosxaplicaciones : usuariosxApps) {
            Solicitud solicitud = new Solicitud();
            Usuario usuario = usuariosxaplicaciones.getIdUsuario();

            Aplicacion aplicacion = usuariosxaplicaciones.getIdAplicacion();
            List<PrivilegioSolicitud> privilegios = localBaseDatos.findPrivilegioByAplicacion(aplicacion.getIdAplicacion());
            StringBuilder nombreUsuario = new StringBuilder(usuario.getNombres());
            EstadosSolicitud estadoSolicitud = new EstadosSolicitud(EstadosSolicitudEnum.POR_APROBAR.getId());
            estadoSolicitud.setNombre(EstadosSolicitudEnum.POR_APROBAR.getEstado());

            //Se obtienen los recursos para ingresarlos en las entidades
            nombreUsuario.append(" ");
            nombreUsuario.append(usuario.getApellidos());
            String descripcion = ResourceBundle.getBundle("mensajes").getString("solicitudAplicacion");
            String aplicacionStr = aplicacion.getNombre();

            //se crea la descripción de la solicitud
            descripcion = MessageFormat.format(descripcion, nombreUsuario.toString(), accion.getNombre(), aplicacionStr);

            //Se llena la entidad solicitud
            solicitud.setActivo(EstadoActividadEnum.ACTIVO.getId());
            solicitud.setDescripcion(descripcion);
            solicitud.setEstado(estadoSolicitud);
            solicitud.setFechaSolicitud(new Date(calendario.getTimeInMillis()));
            solicitud.setIdSolicitante(usuario);
            solicitud.setGerenciaAprobadora(usuario.getGerencia());
            solicitud.setAplicacion(aplicacion);
            solicitud.setUsuario(usuario.getUsername());
            solicitud.setGerenciaAsignadora(localBaseDatos.findAplicacion(aplicacion.getIdAplicacion()).getGerenciaAsignadora());
            solicitud.setAccion(accion.getId());

            solicitudes.add(solicitud);
        }
        return solicitudes;
    }

    private List<Solicitud> generarSolicitudesAdminSolicitudes(Solicitud solicitud) throws ClaroException {
        Calendar calendar = Calendar.getInstance();
        List<Solicitud> solicitudes = new ArrayList<Solicitud>();

        solicitud.setFechaAprobacion(new Date(calendar.getTimeInMillis()));
        solicitud.setEstado(new EstadosSolicitud(EstadosSolicitudEnum.POR_ASIGNAR.getId()));
        solicitudes.add(solicitud);

        solicitud.setUsuario("AdminSolicitudes");
        solicitud.setFechaAsignacion(new Date(calendar.getTimeInMillis()));
        solicitud.setEstado(new EstadosSolicitud(EstadosSolicitudEnum.POR_EJECUTAR.getId()));
        solicitudes.add(solicitud);

        solicitud.setFechaEjecucion(new Date(calendar.getTimeInMillis()));
        solicitud.setEstado(new EstadosSolicitud(EstadosSolicitudEnum.CERRADO.getId()));
        solicitud.setActivo(EstadoActividadEnum.ACTIVO.getId());
        solicitudes.add(solicitud);

        return solicitudes;
    }

    /**
     * Método que arma el mensaje para el correo que se le va a enviar al
     * solicitante de las aplicaciones
     *
     * @param solicitud, solicitud hecha por el usuario
     * @return String, con el mensaje que se enviará por correo.
     */
    private String obtenerMensajeCorreo(Solicitud solicitud, boolean solicitante) {
        String mensaje;
        if (solicitante) {
            mensaje = ResourceBundle.getBundle("mensajesEJB").getString("mensajeSolicitante");

            mensaje = MessageFormat.format(mensaje, solicitud.getIdSolicitud(), solicitud.getEstado().getNombre());
        } else {
            mensaje = ResourceBundle.getBundle("mensajesEJB").getString("mensajeResponsableSolicitud");

            mensaje = MessageFormat.format(mensaje, solicitud.getIdSolicitud());
        }

        return mensaje;
    }

    /**
     * Método que arma el mensaje para el asunto del correo que se le va a
     * enviar tanto al responsable como al usuario de la solicitud.
     *
     * @param idSolicitud, id de la solicitud
     * @return String, con el mensaje del asunto del correo.
     */
    private String obtenerAsuntoSolicitud(Long idSolicitud) {
        String mensaje = ResourceBundle.getBundle("mensajesEJB").getString("mensajeAsuntoSolicitud");

        mensaje = MessageFormat.format(mensaje, idSolicitud);

        return mensaje;
    }

    /**
     * Método que obtiene el correo electrónico de un usuario a través de su
     * username
     *
     * @param username, username dado al usuario en su creación
     * @return String, con el correo electrónico asociado al usuario.
     */
    private String obtenerCorreoUsuarioByUsername(String username) {
        Usuario usuario = localSeguridad.findUsuarioActivoPorUsernameExacto(username);

        if (usuario != null) {
            return usuario.getCorreo();
        }
        return null;
    }

    private void validarSolicitudAplicacion(Solicitud solicitud, AccionesEnum accion) throws ClaroException {
        switch (accion) {
            case CREACION:
                if (localBaseDatos.countUsuarioFijoByIdUsuario(solicitud.getIdSolicitante().getIdUsuario(), solicitud.getAplicacion().getIdAplicacion()) > 0) {
                    throw new ClaroException("El usuario ya tiene asignado username fijo para esa aplicación.");
                }

                List<EstadosSolicitudEnum> estados = new ArrayList<>();
                estados.add(EstadosSolicitudEnum.POR_APROBAR);
                estados.add(EstadosSolicitudEnum.POR_ASIGNAR);
                estados.add(EstadosSolicitudEnum.POR_EJECUTAR);

                List<Solicitud> solicitudes = localBaseDatos.findSolicitudByIdSolicitanteEstadosAccion(solicitud.getIdSolicitante().getIdUsuario(), AccionesEnum.ELIMINACION.getId(), estados);

                if (!solicitudes.isEmpty()) {
                    throw new ClaroException("La solicitud no se pudo crear, aún tiene solicitudes de eliminación pendientes.");
                }
                if (localBaseDatos.countSolicitudesByAplicacionAccionPerfilEstados(solicitud.getAplicacion().getIdAplicacion(), AccionesEnum.CREACION.getId(), solicitud.getPerfil().getIdPerfil(), estados) > 0) {
                    throw new ClaroException("No se puede crear la solicitud. Este usuario ya he hecho una solicitud para obtener acceso a esta aplicacion");
                }

                break;
            default:
                Usuario solicitante = localBaseDatos.findUsuarioByUsernameExacto(solicitud.getIdSolicitante().getUsername());
                Usuario aprobador = localBaseDatos.findUsuarioByUsernameExacto(solicitud.getGerenciaAprobadora().getUsernameAprobador());

                if (solicitante.getIdUsuario() == aprobador.getIdUsuario()) {
                    if (solicitud.getGerenciaAprobadora().getUsernameEscalado() == null) {
                        throw new ClaroException("No se puede procesar la solicitud. El usuario " + solicitante.getNombres() + " " + solicitante.getApellidos()
                                + " es el mismo aprobador, y la gerencia " + solicitud.getGerenciaAprobadora().getNombre() + " no tiene un usuario para escalar la solicitud."
                                + "Por favor comuniquese con el administrador del sistema para solucionar este problema.");
                    }
                }
                break;
        }
    }
}
